<template><div><h2 id="速率限制-限流" tabindex="-1"><a class="header-anchor" href="#速率限制-限流"><span>速率限制（限流）</span></a></h2>
<p>Yii 中文文档 /</p>
<h2 id="速率限制-限流-1" tabindex="-1"><a class="header-anchor" href="#速率限制-限流-1"><span>速率限制（限流）</span></a></h2>
<p>To prevent abuse, you should consider adding <em>rate limiting</em> to your APIs. For example, you may want to limit the API usage of each user to be at most 100 API calls within a period of 10 minutes. If too many requests are received from a user within the stated period of the time, a response with status code 429 (meaning “Too Many Requests”) should be returned.</p>
<p>To enable rate limiting, the [[yii\web\User::identityClass|user identity class]] should implement [[yii\filters\RateLimitInterface]]. This interface requires implementation of three methods:</p>
<ul>
<li><code v-pre>getRateLimit()</code>: returns the maximum number of allowed requests and the time period (e.g., <code v-pre>[100, 600]</code> means there can be at most 100 API calls within 600 seconds).</li>
<li><code v-pre>loadAllowance()</code>: returns the number of remaining requests allowed and the corresponding UNIX timestamp when the rate limit was last checked.</li>
<li><code v-pre>saveAllowance()</code>: saves both the number of remaining requests allowed and the current UNIX timestamp.</li>
</ul>
<p>You may want to use two columns in the user table to record the allowance and timestamp information. With those defined, then <code v-pre>loadAllowance()</code> and <code v-pre>saveAllowance()</code> can be implemented to read and save the values of the two columns corresponding to the current authenticated user. To improve performance, you may also consider storing these pieces of information in a cache or NoSQL storage.</p>
<p>Implementation in the <code v-pre>User</code> model could look like the following:</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">getRateLimit</span><span class="token punctuation">(</span><span class="token variable">$request</span><span class="token punctuation">,</span> <span class="token variable">$action</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token punctuation">[</span><span class="token variable">$this</span><span class="token operator">-></span><span class="token property">rateLimit</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token comment">// $rateLimit requests per second</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">loadAllowance</span><span class="token punctuation">(</span><span class="token variable">$request</span><span class="token punctuation">,</span> <span class="token variable">$action</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token punctuation">[</span><span class="token variable">$this</span><span class="token operator">-></span><span class="token property">allowance</span><span class="token punctuation">,</span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token property">allowance_updated_at</span><span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">saveAllowance</span><span class="token punctuation">(</span><span class="token variable">$request</span><span class="token punctuation">,</span> <span class="token variable">$action</span><span class="token punctuation">,</span> <span class="token variable">$allowance</span><span class="token punctuation">,</span> <span class="token variable">$timestamp</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token variable">$this</span><span class="token operator">-></span><span class="token property">allowance</span> <span class="token operator">=</span> <span class="token variable">$allowance</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token variable">$this</span><span class="token operator">-></span><span class="token property">allowance_updated_at</span> <span class="token operator">=</span> <span class="token variable">$timestamp</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token variable">$this</span><span class="token operator">-></span><span class="token function">save</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Once the identity class implements the required interface, Yii will automatically use [[yii\filters\RateLimiter]] configured as an action filter for [[yii\rest\Controller]] to perform rate limiting check. The rate limiter will throw a [[yii\web\TooManyRequestsHttpException]] when the rate limit is exceeded.</p>
<p>You may configure the rate limiter as follows in your REST controller classes:</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">behaviors</span><span class="token punctuation">(</span><span class="token punctuation">)</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token variable">$behaviors</span> <span class="token operator">=</span> <span class="token keyword static-context">parent</span><span class="token operator">::</span><span class="token function">behaviors</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token variable">$behaviors</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'rateLimiter'</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'enableRateLimitHeaders'</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token constant boolean">false</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token variable">$behaviors</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>When rate limiting is enabled, by default every response will be sent with the following HTTP headers containing the current rate limiting information:</p>
<ul>
<li><code v-pre>X-Rate-Limit-Limit</code>, the maximum number of requests allowed with a time period</li>
<li><code v-pre>X-Rate-Limit-Remaining</code>, the number of remaining requests in the current time period</li>
<li><code v-pre>X-Rate-Limit-Reset</code>, the number of seconds to wait in order to get the maximum number of allowed requests</li>
</ul>
<p>You may disable these headers by configuring [[yii\filters\RateLimiter::enableRateLimitHeaders]] to be <code v-pre>false</code>, as shown in the above code example.</p>
<blockquote>
<p>💖喜欢本文档的，欢迎点赞、收藏、留言或转发，谢谢支持！<br>
作者邮箱：zhuzixian520@126.com，github地址：<a href="https://github.com/zhuzixian520" target="_blank" rel="noopener noreferrer">github.com/zhuzixian520</a></p>
</blockquote>
</div></template>


